//
// Created by 13562 on 2024/4/18.
//

#ifndef VISUAL_LOCATION_PROGRAMCONFIG_H
#define VISUAL_LOCATION_PROGRAMCONFIG_H

#include "rapidjson/document.h"
#include "RapidjsonUtils.h"
#include "CameraParams.h"

#define STEREO_CFG_KEY "stereo-config"

#define DATASET_CFG_KEY "dataset-config"
#define DATASET_CFG_KEY__IMAGE_SET_0 "image_set_0"
#define DATASET_CFG_KEY__IMAGE_SET_1 "image_set_1"
#define DATASET_CFG_KEY__CACHE_SIZE "cache_size"

#define FEATURE_CFG_KEY "feature-config"
#define FEATURE_CFG_KEY__BLOCKS_H "horizontal_blocks"
#define FEATURE_CFG_KEY__BLOCKS_V "vertical_blocks"
#define FEATURE_CFG_KEY__N_FEATURES "n_features"
#define FEATURE_CFG_KEY__FIRST_LEVEL "first_level"
#define FEATURE_CFG_KEY__N_LEVELS "n_levels"
#define FEATURE_CFG_KEY__SCALE_FACTOR "scale_factor"
#define FEATURE_CFG_KEY__PATCH_SIZE "patch_size"
#define FEATURE_CFG_KEY__MIN_DIST_THRESHOLD "min_distance_threshold"

#define YOLO_CFG_KEY "yolo-config"
#define YOLO_CFG_KEY__MODEL "model"

class ProgramConfig {
private:
	rapidjson::Document _dom;
public:
	rapidjson::Value stereoConfigDOM;
	rapidjson::Value datasetConfigDOM;
	rapidjson::Value featureConfigDOM;
	rapidjson::Value yoloConfigDOM;

	typedef struct {
		int n_features;
		int first_level;
		int n_levels;
		float scale_factor;
		int patch_size;
		int feature_blocks_h;
		int feature_blocks_v;
		double min_dist_threshold;
	} FeatureParams;

	typedef struct {
		std::string image_set_0;
		std::string image_set_1;
		int cache_size;
	} DatasetParams;

	typedef struct {
		std::string model;
	} YOLOParams;

	explicit ProgramConfig(const std::string &configFile) {
		_dom = getDOM(configFile);
		stereoConfigDOM = getObjectFrom(_dom, STEREO_CFG_KEY);
		datasetConfigDOM = getObjectFrom(_dom, DATASET_CFG_KEY);
		featureConfigDOM = getObjectFrom(_dom, FEATURE_CFG_KEY);
		yoloConfigDOM = getObjectFrom(_dom, YOLO_CFG_KEY);
	}

	StereoParams getStereoParams() {
		return StereoParams(stereoConfigDOM);
	}

	FeatureParams getFeatureParams() {
		FeatureParams fp;
		fp.feature_blocks_h = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__BLOCKS_H);
		fp.feature_blocks_v = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__BLOCKS_V);
		fp.n_features = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__N_FEATURES);
		fp.first_level = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__FIRST_LEVEL);
		fp.n_levels = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__N_LEVELS);
		fp.scale_factor = float(getDoubleFrom(featureConfigDOM, FEATURE_CFG_KEY__SCALE_FACTOR));
		fp.patch_size = getIntegerFrom(featureConfigDOM, FEATURE_CFG_KEY__PATCH_SIZE);
		fp.min_dist_threshold = getDoubleFrom(featureConfigDOM, FEATURE_CFG_KEY__MIN_DIST_THRESHOLD);
		return fp;
	}

	DatasetParams getDatasetParams() {
		DatasetParams dp;
		dp.image_set_0 = getStringFrom(datasetConfigDOM, DATASET_CFG_KEY__IMAGE_SET_0);
		dp.image_set_1 = getStringFrom(datasetConfigDOM, DATASET_CFG_KEY__IMAGE_SET_1);
		dp.cache_size = getIntegerFrom(datasetConfigDOM, DATASET_CFG_KEY__CACHE_SIZE);
		return dp;
	}

	YOLOParams getYOLOParams() {
		YOLOParams yp;
		yp.model = getStringFrom(yoloConfigDOM, YOLO_CFG_KEY__MODEL);
		return yp;
	}
};

#endif //VISUAL_LOCATION_PROGRAMCONFIG_H
